package de.justphil.tcg.javase.client;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.URI;
import java.net.URISyntaxException;

import javax.swing.JTextArea;
import javax.swing.JLabel;


import de.justphil.websocketclient.WebSocket;
import de.justphil.websocketclient.WebSocketConnection;
import de.justphil.websocketclient.WebSocketException;
import de.justphil.websocketclient.WebSocketListener;
import de.justphil.websocketclient.WebSocketMessage;

public class TCGClient extends JFrame {

	private static final long serialVersionUID = -3505422005253754820L;
	private final JPanel contentPane;
	private final JTextField uriTextField;
	private final JTextArea inputTextArea;
	private final JScrollPane inputScrollPane;
	private final JTextArea outputTextArea;
	private final JScrollPane outputScrollPane;
	private final JLabel connectedLabel;
	private final JButton connectButton;
	private final JButton sendButton;
	
	private WebSocket ws;
	
	public static final String NOT_CONNECTED	= "Not connected!";
	public static final String CONNECTED		= "Connected!";
	public static final String CONNECT			= "Connect";
	public static final String DISCONNECT		= "Disconnect";

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		/* Set Native Look and Feel for the corresponding OS */
		try {
			UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			System.out.println("System LAF set!");
		}
		catch( Exception e ) {
			System.out.println("System LAF couldn't be set!");
			e.printStackTrace();
		}
		
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					TCGClient frame = new TCGClient();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	private void send(String message) {
		if (ws != null && ws.isConnected()) {
			try {
				ws.send(message);
			} catch (WebSocketException e) {
				getOutputTextArea().append("WebSocket Error: " + e.getMessage() + "\n");
			}
		}
	}
	
	private void connectButtonClicked() {
		try {
			if (connectButton.getText().equals(CONNECT)) {
				System.out.println("Connecting to " + uriTextField.getText());
				ws = new WebSocketConnection(new URI(uriTextField.getText()));
				
				ws.setWebSocketListener(new WebSocketListener() {

					@Override
					public void onConnect() {
						getConnectButton().setText(DISCONNECT);
				    	getConnectedLabel().setText(CONNECTED);
				    	getOutputTextArea().setText("");
				    	getOutputTextArea().append("Connected to " + getUriTextField().getText() + "\n");
					}

					@Override
					public void onMessage(WebSocketMessage message) {
						// Determine whether the scrollbar is currently at the very bottom position.
				    	JScrollBar vbar = getOutputScrollPane().getVerticalScrollBar();
				    	boolean autoScroll = ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum());

				    	getOutputTextArea().append(message.getText() + "\n");

				    	// now scroll if we were already at the bottom.
				    	if( autoScroll ) getOutputTextArea().setCaretPosition( getOutputTextArea().getDocument().getLength() );
					}

					@Override
					public void onClose() {
						getConnectButton().setText(CONNECT);
				    	getConnectedLabel().setText(NOT_CONNECTED);
					}
					
				});
				
				ws.connect();
			}
			else {
				ws.close();
				ws = null;
			}
		}
		catch (WebSocketException wse) {
			getOutputTextArea().append("WebSocket Error: " + wse.getMessage() + "\n");
		}
		catch (URISyntaxException use) {
			getOutputTextArea().append("URI Syntax Error: " + use.getMessage() + "\n");
		}
	}

	/**
	 * Create the frame.
	 */
	public TCGClient() {
		setResizable(false);
		setTitle("[55er] WebSocket Client v0.1");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 1200, 597);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		uriTextField = new JTextField();
		uriTextField.setBounds(10, 11, 875, 20);
		uriTextField.setText("ws://localhost:8888/game");
		contentPane.add(uriTextField);
		uriTextField.setColumns(10);
		
		connectButton = new JButton(CONNECT);
		connectButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				TCGClient.this.connectButtonClicked();
			}
		});
		connectButton.setBounds(895, 10, 89, 23);
		contentPane.add(connectButton);
		
		inputTextArea = new JTextArea();
		inputTextArea.setBounds(10, 42, 974, 240);
		
		inputScrollPane = new JScrollPane(inputTextArea);
		inputScrollPane.setBounds(10, 42, 974, 240);
		contentPane.add(inputScrollPane);
		
		outputTextArea = new JTextArea();
		outputTextArea.setBounds(10, 293, 974, 240);
		
		outputScrollPane = new JScrollPane(outputTextArea);
		outputScrollPane.setBounds(10, 293, 974, 240);
		outputScrollPane.getVerticalScrollBar().setVisible(true);
		contentPane.add(outputScrollPane);
		
		JLabel statusLbl = new JLabel("Status:");
		statusLbl.setBounds(839, 544, 46, 14);
		contentPane.add(statusLbl);
		
		connectedLabel = new JLabel(NOT_CONNECTED);
		connectedLabel.setBounds(902, 544, 82, 14);
		contentPane.add(connectedLabel);
		
		sendButton = new JButton("Send Message");
		sendButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (connectButton.getText().equals(DISCONNECT) && ws.isConnected()) {
					send(inputTextArea.getText());
					//inputTextArea.setText("");
				}
			}
		});
		sendButton.setBounds(10, 540, 819, 23);
		contentPane.add(sendButton);
		
		JButton gameJoinButton = new JButton("Game Join Message");
		gameJoinButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-j\",\"l\":\"de-DE\",\"j\":{\"gameId\":1,\"playerId\":1,\"otp\":\"123asd\"}}");
				send(inputTextArea.getText());
			}
			
		});
		gameJoinButton.setBounds(994, 42, 190, 23);
		contentPane.add(gameJoinButton);
		
		JButton gameQuitButton = new JButton("Game Quit Message");
		gameQuitButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-q\"}");
				send(inputTextArea.getText());
			}
			
		});
		gameQuitButton.setBounds(994, 76, 190, 23);
		contentPane.add(gameQuitButton);
		
		JButton attackSlot0Button = new JButton("Attack Slot 0 Message");
		attackSlot0Button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-p\",\"p\":{\"cmd\":\"select\",\"s\":0}}");
				send(inputTextArea.getText());
			}
			
		});
		attackSlot0Button.setBounds(994, 144, 190, 23);
		contentPane.add(attackSlot0Button);
		
		JButton attackSlot1Button = new JButton("Attack Slot 1 Message");
		attackSlot1Button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-p\",\"p\":{\"cmd\":\"select\",\"s\":1}}");
				send(inputTextArea.getText());
			}
			
		});
		attackSlot1Button.setBounds(994, 178, 190, 23);
		contentPane.add(attackSlot1Button);
		
		JButton attackSlot2Button = new JButton("Attack Slot 2 Message");
		attackSlot2Button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-p\",\"p\":{\"cmd\":\"select\",\"s\":2}}");
				send(inputTextArea.getText());
			}
			
		});
		attackSlot2Button.setBounds(994, 212, 190, 23);
		contentPane.add(attackSlot2Button);
		
		JButton gameResumeButton = new JButton("Game Resume Message");
		gameResumeButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getInputTextArea().setText("{\"subject\":\"game-p\",\"p\":{\"cmd\":\"resume\"}}");
				send(inputTextArea.getText());
			}
			
		});
		gameResumeButton.setBounds(994, 110, 190, 23);
		contentPane.add(gameResumeButton);
	}

	public JPanel getContentPane() {
		return contentPane;
	}

	public JTextField getUriTextField() {
		return uriTextField;
	}

	public JTextArea getInputTextArea() {
		return inputTextArea;
	}

	public JTextArea getOutputTextArea() {
		return outputTextArea;
	}
	
	public JScrollPane getOutputScrollPane() {
		return outputScrollPane;
	}

	public JLabel getConnectedLabel() {
		return connectedLabel;
	}

	public JButton getConnectButton() {
		return connectButton;
	}

	public JButton getSendButton() {
		return sendButton;
	}
}
